import { $each } from '../index';
import { isNullOrEmpty, isEmptyObject, isEmptyArr, isArray, isNumber, isObject } from '../is';
import {
  set as $lodashSet,
  get as $lodashGet,
  cloneDeep as $deepClone,
  merge as $lodashMerge,
} from 'lodash-es';

import { formSmartToScreen } from '../fetchParams/index.js';

/**
 * 根据不同的category进行数据的转换
 * @param { String } category : 过滤条件的所属分类
 * @param {*} condition：当前过滤条件
 * @param {*} relationItem: 存储的关系item
 * @returns 过滤条件
 */
function formatConditionWithType(category, condition, relationItem, filter) {
  // 存在值进行拼接请求参数
  if (condition.category === category && condition.value) {
    const { name, alias, datasetFieldName } = relationItem;
    filter.name = name;
    filter.alias = alias;
    filter.datasetFieldName = datasetFieldName;
    // 是否是更多选择里的选项
    if ('MultiSelect' === condition.componentName) {
      // 根据value获取在map中获取传给后端的值
      condition.map[condition.value] && (filter[category] = condition.map[condition.value]);
      return;
    }
    // value是否为复杂类型时为其本身
    if (isObject(condition.value) && !isEmptyObject(condition.value)) {
      filter[category] = condition.value;
      return;
    }
    condition[category] && (filter[category] = condition[category]);
  }
}

/**
 * 转换filter
 * @param {*} filterItem: 过滤的条件
 * @param {*} sortIndex：排序下表
 */
export function formatFilterItem(filterItem, sortIndex) {
  const filter = {};
  const { name, alias, datasetFieldName, catalogTableColumnType } = filterItem;
  filter.name = name;
  filter.alias = alias;
  filter.datasetFieldName = datasetFieldName;
  // 日期类型需添加特殊的dataFormat
  if ('TIMESTAMP' === catalogTableColumnType) {
    filter.dateFormat = 'YYYY_MM_DD';
  }
  $each(filterItem.conditions, (condition) => {
    // 过滤排序条件
    formatConditionWithType('sort', condition, filterItem, filter);
    // 度量的聚合函数
    formatConditionWithType('function', condition, filterItem, filter);
    // 时间的分组函数
    formatConditionWithType('dateFormat', condition, filterItem, filter);
    // 含有结果过滤
    formatConditionWithType('filter', condition, filterItem, filter);
    // 同环比
    formatConditionWithType('compareType', condition, filterItem, filter);

    // 对sort进行sortIndex处理
    if ('sort' === condition.category && filter.sort && sortIndex) {
      filter.sortIndex = sortIndex.index++;
    }
  });
  return filter;
}

/**
 * 根据钻取深度替换掉当前的维度条件
 * @param {*} filterItem: 维度条件
 * @param {*} drillList：下钻集合
 * @param {*} depth：下钻深度
 */
export function replaceItem(filterItem, drillList, depth) {
  if (Array.isArray(drillList) && drillList.length > 0) {
    Object.assign(filterItem, drillList[depth], { conditions: [] });
  }
}

/**
 *  TODO: 去除convertRelationToParams里特殊的数据
 * 不同的图表参数会存在差异
 * 交叉表、明细表会需要分页数据
 * 交叉表发布后的需要全量数据
 * @param {*} requestParams：公共部分的参数
 * @param {*} options：混入的参数
 */
/* eslint-disable no-unused-vars */
function mixinExtraCondition(requestParams, option) {
  Object.assign(requestParams, option);
}

/**
 * 不同字段类型对应的不同表达式
 */
export const expressionConfig = {
  TEXT: (value, formatType = 'BELONG') => ({
    conditionType: formatType,
    value:  Array.isArray(value) ? value : [value],
  }),
  STRING: (value, formatType = 'BELONG') => ({
    conditionType: formatType,
    value:  Array.isArray(value) ? value : [value],
  }),
  DECIMAL: (value) => ({
    conditionType: 'EQUALS',
    value,
  }),
  TIMESTAMP: (value) => {
    let min = value;
    let max = value;
    if (Array.isArray(value)) {
      [min, max] = value;
    }
    return {
      conditionType: 'BETWEEN',
      value: {
        min: {
          type: 'GE',
          value: min,
        },
        max: {
          type: 'LE',
          value: max,
        },
      },
    };
  },
  DATE: (value) => {
    let min = value;
    let max = value;
    if (Array.isArray(value)) {
      [min, max] = value;
    }
    return {
      conditionType: 'BETWEEN',
      value: {
        min: {
          type: 'GE',
          value: min,
        },
        max: {
          type: 'LE',
          value: max,
        },
      },
    };
  },
};

/**
 * 根据过滤参数生成指定的过滤条件
 * 适用于下钻item和联动item
 * @param {*} filterItem: 下钻item和联动item
 */
export function generateFilterCondition(filterItem, filterValue, formatType) {
  if (!filterItem) {
    return;
  }
  const {
    datasetFieldName,
    catalogTableColumnType: nodeColumnType,
    name: nodeColumnName,
    tableId,
    filterDateFormat,
  } = filterItem;
  const expression = {
    filterType: 'CONDITION',
    filterCondition: $lodashMerge(
      {
        conditionType: '',
        dateFormat: filterDateFormat || 'YYYY_MM_DD',
        datasetFieldName,
        nodeColumnName,
        nodeColumnType,
        tableId,
        value: null,
      },
      // 根据字段类型不同拼装不同表达式
      expressionConfig[nodeColumnType](filterValue,  formatType),
    ),
  };

  return { filter: { operator: 'AND', children: [{ expression }] } };
}
/**
 * 根据过滤参数生成指定的过滤条件
 * 适用于级联选择器中的联动item
 * @param {*} filterItem: 联动item
 */
function generateCascaderFilterCondition(filterItem) {
  if (isEmptyArr(filterItem)) {
    return;
  }
  const filterChildren = [];
  filterItem.forEach((item) => {
    const {
      datasetFieldName,
      catalogTableColumnType: nodeColumnType,
      name: nodeColumnName,
      tableId,
      filterDateFormat,
      filterValue,
    } = item;
    const expression = {
      filterType: 'CONDITION',
      filterCondition: $lodashMerge(
        {
          conditionType: '',
          dateFormat: filterDateFormat || 'YYYY_MM_DD',
          datasetFieldName,
          nodeColumnName,
          nodeColumnType,
          tableId,
          value: null,
        },
        // 根据字段类型不同拼装不同表达式
        expressionConfig[nodeColumnType](filterValue),
      ),
    };
    filterChildren.push({ expression });
  });
  return { filter: { operator: 'AND', children: filterChildren } };
}
/**
 * 处理特殊情况下的过滤条件
 * @param {*} requestParams：过滤条件
 */
function processFilterCondition(requestParams, options) {
  // 如果不存在过滤条件，则不需要处理
  if (!requestParams['filterConditionTree']) {
    return;
  }

  // 过滤掉为{}的数据
  requestParams['filterConditionTree'] = requestParams['filterConditionTree'].filter(
    (item) => !isEmptyObject(item),
  );
  // 根据下钻生成特定的过滤条件表达式
  const {
    drillList,
    drillBreadcrumbs,
    linkageList,
    filterList,
    chartType,
    globalParameterFilters,
    jumpFilterList,
  } = options;
  if (chartType.includes('map')) {
    // 不同级别的地理信息，对应的下钻面包屑的索引
    const geographyIndexMap = {
      COUNTRY: 1,
      PROVINCE: 2,
      CITY: 3,
      DISTRICT: 4,
    };
    $each(drillList || [], (drillItem) => {
      if (!drillBreadcrumbs[geographyIndexMap[drillItem.geographyType]]?.label) {
        return;
      }
      const  { value , label } = drillBreadcrumbs[geographyIndexMap[drillItem.geographyType]];
      requestParams['filterConditionTree'].unshift(
        generateFilterCondition(
          drillItem,
          label==='中国' ? value :label,
        ),
      );
    });
  } else {
    $each(drillBreadcrumbs, (breadcrumb, index) => {
      if (index > 0) {
        requestParams['filterConditionTree'].unshift(
          generateFilterCondition(drillList[index - 1], breadcrumb.label),
        );
      }
    });
  }
  // 添加全局变量过滤（地址栏参数）,添加跳转设置的目标字段过滤
  const formatType = formSmartToScreen(['conditionType']).conditionType;
  $each([...globalParameterFilters, ...jumpFilterList], (item) => {
    const { filterValue, field } = item;
      // 这里用暴露出来的方法
    requestParams['filterConditionTree'].unshift(generateFilterCondition(field, filterValue, formatType));
  });

  // 时间筛选器2（seriesType='dateBase'）选中的日期，要放到结果过滤的“最晚的N个”和“最早的N个”类型中作为基准日期
  const linkageApplyConditionTypes = ['LITTLE_N', 'TOP_N'];
  let linkageApplyed = false; // 结果过滤条件中是否存在“最晚的N个”和“最早的N个”过滤条件
  const setLinkageValueToFilter = (
    filterConditionTree,
    filterDateFormat,
    filterValue,
    dimensionDateFormat,
  ) => {
    const conditionType = $lodashGet(
      filterConditionTree,
      'expression.filterCondition.conditionType',
    );
    if (linkageApplyConditionTypes.includes(conditionType)) {
      linkageApplyed = true;
      const linkageValueEmpty = !filterValue || !filterValue[0]; // 时间筛选器的值是否为空
      $lodashSet(
        filterConditionTree,
        'expression.filterCondition.dateFormat',
        linkageValueEmpty ? dimensionDateFormat : filterDateFormat,
      );
      $lodashSet(
        filterConditionTree,
        'expression.filterCondition.referenceValue',
        linkageValueEmpty ? '' : filterValue[0],
      );
    }
    const { children } = filterConditionTree;
    if (children && !isEmptyArr(children)) {
      children.forEach((filterChild) =>
        setLinkageValueToFilter(filterChild, filterDateFormat, filterValue, dimensionDateFormat),
      );
    }
  };
  // 过滤联动信息
  $each(linkageList, (item) => {
    if (item.seriesType === 'dateBase') {
      // 如果联动类型是时间筛选器2
      const { filterDateFormat, filterValue, datasetFieldName } = item;
      // 给维度设置时间筛选器2的日期格式
      const dimensionField = requestParams['dimensionFieldList'].find(
        (item) => item.datasetFieldName === datasetFieldName,
      );
      const { dateFormat: dimensionDateFormat = 'YYYY_MM_DD' } = dimensionField || {};
      if (dimensionField && filterValue && filterValue[0]) {
        dimensionField.dateFormat = filterDateFormat;
      }
      // 给“最晚的N个”和“最早的N个”过滤条件，设置时间筛选器2的日期格式和基准日期
      $each(requestParams['filterConditionTree'], (filterRelation) => {
        if (filterRelation.datasetFieldName === datasetFieldName) {
          setLinkageValueToFilter(
            filterRelation.filter,
            filterDateFormat,
            filterValue,
            dimensionDateFormat,
          );
        }
      });
    }
    if (!linkageApplyed) {
      // 如果联动的值没有应用到过滤条件中，将联动条件添加到filterConditionTree
      // 级联选择器需要另外区分，item为数组
      if (isArray(item)) {
        requestParams['filterConditionTree'].unshift(generateCascaderFilterCondition(item));
        return;
      }
      // 树形组件要用belong判断条件
      if (item.seriesType === 'control_treeSelect') {
        requestParams['filterConditionTree'].unshift(generateFilterCondition(item, item.filterValue, 'BELONG'));
      } else {
        requestParams['filterConditionTree'].unshift(generateFilterCondition(item, item.filterValue));
      }
    }
  });

  // 数据过滤信息
  $each(filterList, (item) => {
    requestParams['filterConditionTree'].unshift(generateFilterCondition(item, item.filterValue));
  });

  // 需要处理特殊的结果过滤，后端需要进行表达式拼接
  if (requestParams['filterConditionTree'].length > 1) {
    requestParams['filterConditionTree'] = {
      operator: linkageList && isArray(linkageList[0]) ? 'OR' : 'AND', // 级联选择器的linkageList是数组内包含多个数组,用‘OR’拼接
      expression: {},
      children: requestParams['filterConditionTree'].map((item) => item && item.filter),
    };
  } else if (requestParams['filterConditionTree'].length === 1) {
    requestParams['filterConditionTree'] = requestParams['filterConditionTree'].shift()?.filter;
  } else {
    requestParams['filterConditionTree'] = {};
  }
}

/**
 * 转换请求参数
 */
export function formatCondition() {
  // 字段信息
  let relationMap = {};
  // 下钻数据集合
  let drillList = [];
  // 下钻面包屑集合
  let drillBreadcrumbs = [];
  // 联动信息
  let linkageList = [];
  // 组件过滤信息
  let filterList = [];
  // 全局参数对应的字段及字段值
  let globalParameterFilters = [];
  // 跳转过滤对应的字段及字段值
  let jumpFilterList = [];

  /**
   * 重置relationMap，在新拖拽/删除图表的时候，会发生变化，需要重新赋值
   * @param {object} newRelationMap - 字段信息
   */
  function resetRelationMap(newRelationMap = {}) {
    relationMap = JSON.parse(JSON.stringify(newRelationMap));
  }

  /**
   * 重置drill，在新拖拽/删除图表的时候，会发生变化，需要重新赋值
   * @param {array} config - 下钻信息
   */
  function resetDrillList(config = []) {
    drillList = config ? JSON.parse(JSON.stringify(config)) : [];
  }
  /**
   * 重置下钻面包屑信息
   * @param {array} config - 面包屑信息
   */
  function resetDrillBreadcrumbs(config = []) {
    drillBreadcrumbs = config ? JSON.parse(JSON.stringify(config)) : [];
  }

  /**
   * 联动信息
   * @param {array} config - 联动信息
   */
  function resetLinkageList(config = []) {
    linkageList = config ? $deepClone(config) : [];
  }
  /**
   * 过滤信息
   * @param {array} config - 过滤信息
   */
  function resetFilterList(config = []) {
    filterList = config ? $deepClone(config) : [];
  }
  /**
   * 全局参数信息
   * @param {array} config - 全局参数信息
   */
  function resetGlobalParameterFilters(config = []) {
    globalParameterFilters = config ? $deepClone(config) : [];
  }
  /**
   * 跳转信息
   * @param {array} config - 跳转信息
   */
  function resetJumpFilters(config = []) {
    jumpFilterList = config ? $deepClone(config) : [];
  }

  /**
   * 根据字段信息转换为后端所需要的参数
   * @param {object} constantMap - 前后端不同的映射配置
   * @param {string|undefined} chartType - 组件类型
   * @returns {object} 请求参数 和 响应关系
   */
  function convertRelationToParams(constantMap, options = {}) {
    const { chartType = '', seriesType, pagination, componentKey,geoMap } = options;
    // 请求的参数
    let requestParams = {};
    // 找到对应的值
    $each(constantMap, (paramsKey) => {
      requestParams[paramsKey] = [];
    });
    // relation关系
    const responseRelations = {};
    // 多个relationItem, 后端排序需要传输sortIndex
    const sortIndex = { index: 0 };
    // 生成后端所需要的参数
    $each(relationMap, (relationItem, relationKey) => {
      //TODO--暂时修改 文本组件，拖入度量时，拖入的信息要存到valueFieldList中拿到总合
      const key =
        componentKey === 'info_text' && relationItem.relations.length
          ? isValueField(relationItem, relationKey)
          : relationKey;
      if (constantMap[key]) {
        // format需要的响应关系
        responseRelations[key] = relationItem;
        // 转换filterItem to condition
        $each(relationItem.relations, (filterItem) => {
          // 开启了钻取
          if (filterItem.isDrilled && drillBreadcrumbs.length > 1) {
            if (chartType.includes('map') && !geoMap.includes('world')) {
              // TODO 根据钻取深度替换过滤条件，注：地图的“世界”层级暂不支持下钻，所以获取下钻深度时需要相对于面包屑的索引减一；此为临时方案，后续需要修改
              replaceItem(filterItem, drillList, drillBreadcrumbs.length - 2);
            } else {
              // 根据钻取深度替换过滤条件
              replaceItem(filterItem, drillList, drillBreadcrumbs.length - 1);
            }
          }

          // 拼装request参数
          if (constantMap[key]) {
            requestParams[constantMap[key]].push(formatFilterItem(filterItem, sortIndex));
          }
        });
      }
    });

    // 需要特殊处理过滤参数
    processFilterCondition(requestParams, {
      drillList,
      drillBreadcrumbs,
      linkageList,
      filterList,
      globalParameterFilters,
      jumpFilterList,
      chartType,
      seriesType,
    });

    if (!isNullOrEmpty(pagination)) {
      requestParams = { ...requestParams, ...pagination }; // 增加分页信息
    }

    return { requestParams, responseRelations };
  }
  /**
   * 判断是否是文本组件并且拖的是度量
   */
  function isValueField(relationItem, relationKey) {
    let key = relationKey;
    if (relationKey === 'xAxis' && relationItem.relations[0].dataType !== 'STRING') {
      key = 'yAxis';
    }
    return key;
  }
  /**
   * 转换echarts需要的参数
   */
  function formatEcharts(options = {}) {
    // 映射字段
    const constantMap = {
      xAxis: 'dimensionFieldList',
      xAxisArea: 'dimensionFieldList',
      xAxisMap: 'dimensionFieldList',
      yAxisTitle: 'valueFieldList',
      yAxisHide: 'valueFieldList',
      yAxisComment: 'valueFieldList',
      yAxisDate: 'valueFieldList',
      yAxis: 'valueFieldList',
      xAxisScatter: 'valueFieldList',
      yAxisSize: 'valueFieldList',
      legend: 'legendFieldList',
      filter: 'filterConditionTree',
      yAxisLine: 'colorFieldList',
      yAxisBar: 'colorFieldList',
      yAxisColor: 'colorFieldList',
      yAxisAreaColor: 'valueFieldList',
      yAxisCondition: 'valueFieldList',
      yAxisProgress: 'valueFieldList',
      // 预测图度量数据拼装
      yAxisRealBar: 'valueFieldList',
      yAxisEmptyBar: 'valueFieldList',
      yAxisRealLine: 'valueFieldList',
      yAxisEmptyLine: 'valueFieldList',
    };
    const { requestParams, responseRelations } = convertRelationToParams(constantMap, options);
    // 后端要求颜色维度也传到维度里
    requestParams.dimensionFieldList.push(...requestParams.legendFieldList);
    // TODO：全量数据标识
    const { fullData, datasourceId, tableName } = options;
    // 混入全量标识参数给后端
    mixinExtraCondition(requestParams, { fullData, datasourceId, tableName });
    /*
     * 临时解决，散点图气泡大小和气泡颜色度量
     * 后续进行优化
     */
    !isNullOrEmpty(requestParams.valueFieldList) &&
      !isNullOrEmpty(requestParams.colorFieldList) &&
      requestParams.valueFieldList.push(...requestParams.colorFieldList);
    return { requestParams, responseRelations };
  }

  /**
   * 转换明细表所需要的参数
   */

  function formatCommonTable(options = {}) {
    const { pagination } = options;
    const PAGESIZE = 10;
    // 需要分页信息
    const constantMap = {
      xAxis: 'valueFieldList', // 因为列选项一个需要配置，因此将xAxis字段调整成valueFieldList
      yAxis: 'rowFieldList',
      yAxisProgress: 'valueFieldList',
      yAxisCondition: 'valueFieldList',
      legend: 'headFieldList',
      filter: 'filterConditionTree',
    };
    const paginationParams = {
      // 构建分页信息
      pageSize: (pagination && pagination.pageSize) || PAGESIZE,
      pageNo: (pagination && pagination.pageNo) || 1,
    };
    options.pagination = paginationParams;
    const { requestParams, responseRelations } = convertRelationToParams(constantMap, options);
    /*
     * 后端要求颜色维度也传到维度里
     * requestParams.dimensionFieldList.push(...requestParams.legendFieldList);
     */
    return { requestParams, responseRelations };
  }

  /**
   * 转换交叉表所需要的参数
   */
  function formatCrossTable() {
    // 需要分页信息
    const constantMap = {
      xAxis: 'headFieldList',
      yAxis: 'rowFieldList',
      legend: 'valueFieldList',
      filter: 'filterConditionTree',
    };
    const { requestParams, responseRelations } = convertRelationToParams(constantMap);
    // 后端要求颜色维度也传到维度里

    // requestParams.dimensionFieldList.push(...requestParams.legendFieldList);
    return { requestParams, responseRelations };
  }

  /**
   * 文本筛选
   */
  function formatTextFilter() {
    const constantMap = {
      xAxis: 'dimensionFieldList',
      yAxis: 'valueFieldList',
      legend: 'legendFieldList',
      filter: 'filterConditionTree',
    };
    const { requestParams, responseRelations } = convertRelationToParams(constantMap);
    return { requestParams, responseRelations };
  }

  /**
   * 转换请求HT 3D模型数据的参数
   * @param {String} componentId 当前组件的id
   * @param {Object} options 选项对象，数据结构：
   * {
   *   relationOptionIndex: 0 // 当前关联数据的图层索引
   * }
   */
  function formatHt3DModelData(componentId, options) {
    const { relationOptionIndex } = options || {};
    const constantMap = generateCommonConstantMap(componentId, { relationOptionIndex });
    const { requestParams, responseRelations } = convertRelationToParams(constantMap);
    requestParams.valueFieldList = [];
    return { requestParams, responseRelations };
  }

  /**
   * 生成通用的constantMap，即：所有组件关联的字段，都放到同一个请求字段里
   * @param {String} componentId 组件id
   * @param {Object} options 选项对象，数据结构：
   * {
   *   requestFieldName: 'dimensionFieldList', // 请求的字段名，默认为“dimensionFieldList”
   *   relationOptionIndex: 0 // 当前关联数据的图层索引，如果不分图层则不传该参数
   * }
   * @param {String} requestFieldName 请求的字段名
   * @param {String} relationOptionIndex 组件图层的索引
   */
  function generateCommonConstantMap(componentId, options) {
    const { requestFieldName = 'dimensionFieldList', relationOptionIndex } = options || {};
    const constantMap = {};
    $each(relationMap, (relationItem, relationKey) => {
      if (
        // 如果不是当前组件的关联属性，则不处理
        !relationKey.includes(componentId) ||
        // 如果组件分了图层，且不是当前图层，则不处理
        (isNumber(relationOptionIndex) && !relationKey.includes(`.${relationOptionIndex}|`))
      ) {
        return;
      }

      // 将当前的属性key加到constantMap中，value为请求接口时的字段名
      const [, , interfaceParamsKey] = relationKey.split('.');
      constantMap[interfaceParamsKey] = requestFieldName;
    });
    return constantMap;
  }

  return {
    // 重置relation关系
    resetRelationMap,
    // 重置drill关系
    resetDrillList,
    // 重置drill面包屑信息
    resetDrillBreadcrumbs,
    // 重置联动信息
    resetLinkageList,
    // 重置过滤信息
    resetFilterList,
    // 重置全局参数信息
    resetGlobalParameterFilters,
    // 重置跳转过滤信息
    resetJumpFilters,
    format: {
      formatEcharts,
      formatCommonTable,
      formatCrossTable,
      formatTextFilter,
      formatHt3DModelData,
    },
  };
}
